﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Runtime.InteropServices;
using WebStudio.Framework.Helper;

namespace WebStudio.Framework.Service
{
    public class ServiceInstaller
    {
        // Methods
        public bool ChangeServiceStartType(string serviceName, bool isAutoStart)
        {
            IntPtr hSCManager = IntPtr.Zero;
            IntPtr hSCManagerLock = IntPtr.Zero;
            IntPtr hService = IntPtr.Zero;
            bool result = true;
            try
            {
                hSCManager = InstallerAPI.OpenSCManager(null, null, InstallerAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);
                if (hSCManager == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "不能打开服务控制台！");
                }
                hSCManagerLock = InstallerAPI.LockServiceDatabase(hSCManager);
                if (hSCManagerLock == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "无法锁定服务控制台");
                }
                hService = InstallerAPI.OpenService(hSCManager, serviceName, InstallerAPI.ACCESS_TYPE.SERVICE_ALL_ACCESS);
                if (hService == IntPtr.Zero)
                {
                    throw new ApplicationException("不能打开指定服务");
                }
                result = InstallerAPI.ChangeServiceConfig(hService, InstallerAPI.ServiceType.SERVICE_WIN32_OWN_PROCESS, isAutoStart ? InstallerAPI.ServiceStartType.SERVICE_AUTO_START : InstallerAPI.ServiceStartType.SERVICE_DEMAND_START, -1, null, null, 0, null, null, null, null);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "无法修改服务配置");
                }
            }
            catch (Exception objExp)
            {
                if (objExp.GetType() != Type.GetType("System.ApplicationException"))
                {
                    ExceptionHelper.Handle(objExp);
                }
                result = false;
            }
            finally
            {
                if (hService != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hService);
                    hService = IntPtr.Zero;
                }
                if (hSCManagerLock != IntPtr.Zero)
                {
                    InstallerAPI.UnlockServiceDatabase(hSCManagerLock);
                    hSCManagerLock = IntPtr.Zero;
                }
                if (hSCManager != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hSCManager);
                    hSCManager = IntPtr.Zero;
                }
            }
            return result;
        }

        public InstallerAPI.ServiceStartType GetServiceStartType(string serviceName)
        {
            IntPtr hSCManager = IntPtr.Zero;
            IntPtr hService = IntPtr.Zero;
            int flag = 4;
            try
            {
                hSCManager = InstallerAPI.OpenSCManager(null, null, InstallerAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);
                if (hSCManager == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "不能打开服务控制台！");
                }
                hService = InstallerAPI.OpenService(hSCManager, serviceName, InstallerAPI.ACCESS_TYPE.SERVICE_ALL_ACCESS);
                if (hService == IntPtr.Zero)
                {
                    throw new ApplicationException("不能打开指定服务");
                }
                InstallerAPI.QUERY_SERVICE_CONFIG config = new InstallerAPI.QUERY_SERVICE_CONFIG();
                IntPtr ptr = Marshal.AllocHGlobal(0x1000);
                int needBytes = 0;
                bool result = InstallerAPI.QueryServiceConfig(hService, ptr, 0x1000, ref needBytes);
                Marshal.PtrToStructure(ptr, config);
                Marshal.FreeHGlobal(ptr);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "获取服务启动类型失败！");
                }
                flag = config.dwStartType;
            }
            catch (Exception objExp)
            {
                if (objExp.GetType() != Type.GetType("System.ApplicationException"))
                {
                    ExceptionHelper.Handle(objExp);
                }
                flag = 4;
            }
            finally
            {
                if (hService != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hService);
                    hService = IntPtr.Zero;
                }
                if (hSCManager != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hSCManager);
                    hSCManager = IntPtr.Zero;
                }
            }
            return (InstallerAPI.ServiceStartType)flag;
        }

        public InstallerAPI.ServiceState GetServiceState(string serviceName)
        {
            IntPtr hSCManager = IntPtr.Zero;
            IntPtr hService = IntPtr.Zero;
            int flag = 0;
            try
            {
                hSCManager = InstallerAPI.OpenSCManager(null, null, InstallerAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);
                if (hSCManager == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "不能打开服务控制台！");
                }
                hService = InstallerAPI.OpenService(hSCManager, serviceName, InstallerAPI.ACCESS_TYPE.SERVICE_ALL_ACCESS);
                if (hService == IntPtr.Zero)
                {
                    throw new ApplicationException("不能打开指定服务");
                }
                InstallerAPI.SERVICE_STATUS_PROCESS status = new InstallerAPI.SERVICE_STATUS_PROCESS();
                int needBytes = 0;
                if (!InstallerAPI.QueryServiceStatusEx(hService, InstallerAPI.ServiceStatusType.SC_STATUS_PROCESS_INFO, ref status, 0x24, ref needBytes))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "获取服务状态失败！");
                }
                flag = status.dwCurrentState;
            }
            catch
            {
                flag = 0;
            }
            finally
            {
                if (hService != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hService);
                    hService = IntPtr.Zero;
                }
                if (hSCManager != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hSCManager);
                    hSCManager = IntPtr.Zero;
                }
            }
            return (InstallerAPI.ServiceState)flag;
        }

        public bool InstallService(string servicePath, string serviceName, string serviceDispName, string serviceDescription, bool isAutoStart)
        {
            IntPtr hSCManager = IntPtr.Zero;
            IntPtr hSCManagerLock = IntPtr.Zero;
            IntPtr hService = IntPtr.Zero;
            bool result = true;
            try
            {
                hSCManager = InstallerAPI.OpenSCManager(null, null, InstallerAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);
                if (hSCManager == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "不能打开服务控制台！");
                }
                hSCManagerLock = InstallerAPI.LockServiceDatabase(hSCManager);
                if (hSCManagerLock == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "无法锁定服务控制台");
                }
                hService = InstallerAPI.CreateService(hSCManager, serviceName, serviceDispName, InstallerAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS, InstallerAPI.ServiceType.SERVICE_WIN32_OWN_PROCESS, isAutoStart ? InstallerAPI.ServiceStartType.SERVICE_AUTO_START : InstallerAPI.ServiceStartType.SERVICE_DEMAND_START, InstallerAPI.ServiceErrorControl.SERVICE_ERROR_NORMAL, servicePath, null, 0, null, null, null);
                if (hService == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "创建服务失败！");
                }
                InstallerAPI.SERVICE_DESCRIPTION description = new InstallerAPI.SERVICE_DESCRIPTION();
                description.lpDescription = serviceDescription;
                result = InstallerAPI.ChangeServiceConfig2(hService, InstallerAPI.InfoLevel.SERVICE_CONFIG_DESCRIPTION, ref description);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "无法修改服务描述");
                }
                InstallerAPI.SERVICE_FAILURE_ACTIONS failureActions = new InstallerAPI.SERVICE_FAILURE_ACTIONS();
                failureActions.dwResetPeriod = 600;
                failureActions.lpRebootMsg = "服务启动失败! 正在重启中...";
                failureActions.lpCommand = "";
                InstallerAPI.SC_ACTION[] actions = new InstallerAPI.SC_ACTION[3];
                failureActions.cActions = actions.Length;
                actions[0].Delay = 0x7530;
                actions[0].SCActionType = InstallerAPI.SC_ACTION_TYPE.SC_ACTION_RESTART;
                actions[1].Delay = 0x7530;
                actions[1].SCActionType = InstallerAPI.SC_ACTION_TYPE.SC_ACTION_RESTART;
                actions[2].Delay = 0x7530;
                actions[2].SCActionType = InstallerAPI.SC_ACTION_TYPE.SC_ACTION_NONE;
                IntPtr ptrScActions = new IntPtr();
                ptrScActions = Marshal.AllocHGlobal((int)(Marshal.SizeOf(new InstallerAPI.SC_ACTION()) * 3));
                InstallerAPI.CopyMemory(ptrScActions, actions, Marshal.SizeOf(new InstallerAPI.SC_ACTION()) * 3);
                failureActions.lpsaActions = ptrScActions.ToInt32();
                result = InstallerAPI.ChangeServiceConfig2(hService, InstallerAPI.InfoLevel.SERVICE_CONFIG_FAILURE_ACTIONS, ref failureActions);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "无法设置服务的故障恢复模式");
                }
            }
            catch (Exception objExp)
            {
                ExceptionHelper.Handle(objExp);
                result = false;
            }
            finally
            {
                if (hService != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hService);
                    hService = IntPtr.Zero;
                }
                if (hSCManagerLock != IntPtr.Zero)
                {
                    InstallerAPI.UnlockServiceDatabase(hSCManagerLock);
                    hSCManagerLock = IntPtr.Zero;
                }
                if (hSCManager != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hSCManager);
                    hSCManager = IntPtr.Zero;
                }
            }
            return result;
        }

        public bool StartService(string serviceName)
        {
            IntPtr hSCManager = IntPtr.Zero;
            IntPtr hService = IntPtr.Zero;
            bool result = true;
            try
            {
                hSCManager = InstallerAPI.OpenSCManager(null, null, InstallerAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);
                if (hSCManager == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "不能打开服务控制台！");
                }
                hService = InstallerAPI.OpenService(hSCManager, serviceName, InstallerAPI.ACCESS_TYPE.SERVICE_ALL_ACCESS);
                if (hService == IntPtr.Zero)
                {
                    throw new ApplicationException("不能打开指定服务");
                }
                if (InstallerAPI.StartService(hService, 0, null) == 0)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "启动指定的服务失败！");
                }
            }
            catch (Exception objExp)
            {
                if (objExp.GetType() != Type.GetType("System.ApplicationException"))
                {
                    ExceptionHelper.Handle(objExp);
                }
                result = false;
            }
            finally
            {
                if (hService != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hService);
                    hService = IntPtr.Zero;
                }
                if (hSCManager != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hSCManager);
                    hSCManager = IntPtr.Zero;
                }
            }
            return result;
        }

        public bool StopService(string serviceName)
        {
            IntPtr hSCManager = IntPtr.Zero;
            IntPtr hService = IntPtr.Zero;
            bool result = true;
            try
            {
                hSCManager = InstallerAPI.OpenSCManager(null, null, InstallerAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);
                if (hSCManager == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "不能打开服务控制台！");
                }
                hService = InstallerAPI.OpenService(hSCManager, serviceName, InstallerAPI.ACCESS_TYPE.SERVICE_ALL_ACCESS);
                if (hService == IntPtr.Zero)
                {
                    throw new ApplicationException("不能打开指定服务");
                }
                InstallerAPI.SERVICE_STATUS status = new InstallerAPI.SERVICE_STATUS();
                result = InstallerAPI.ControlService(hService, InstallerAPI.ServiceControlType.SERVICE_CONTROL_STOP, ref status);
                if (!result)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "停止指定的服务失败！");
                }
            }
            catch (Exception objExp)
            {
                if (objExp.GetType() != Type.GetType("System.ApplicationException"))
                {
                    ExceptionHelper.Handle(objExp);
                }
                result = false;
            }
            finally
            {
                if (hService != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hService);
                    hService = IntPtr.Zero;
                }
                if (hSCManager != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hSCManager);
                    hSCManager = IntPtr.Zero;
                }
            }
            return result;
        }

        public bool UnInstallService(string serviceName)
        {
            IntPtr hSCManager = IntPtr.Zero;
            IntPtr hService = IntPtr.Zero;
            bool result = true;
            try
            {
                hSCManager = InstallerAPI.OpenSCManager(null, null, InstallerAPI.ServiceControlManagerType.SC_MANAGER_ALL_ACCESS);
                if (hSCManager == IntPtr.Zero)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "不能打开服务控制台！");
                }
                hService = InstallerAPI.OpenService(hSCManager, serviceName, InstallerAPI.ACCESS_TYPE.SERVICE_ALL_ACCESS);
                if (hService == IntPtr.Zero)
                {
                    throw new ApplicationException("不能打开指定服务");
                }
                if (InstallerAPI.DeleteService(hService) == 0)
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error(), "删除指定的服务失败！");
                }
            }
            catch (Exception objExp)
            {
                if (objExp.GetType() != Type.GetType("System.ApplicationException"))
                {
                    ExceptionHelper.Handle(objExp);
                }
                result = false;
            }
            finally
            {
                if (hService != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hService);
                    hService = IntPtr.Zero;
                }
                if (hSCManager != IntPtr.Zero)
                {
                    InstallerAPI.CloseServiceHandle(hSCManager);
                    hSCManager = IntPtr.Zero;
                }
            }
            return result;
        }

    }
}
